/* data structure for characteristics
 *
 * Copyright (C) 2008 Ed Hong
 * 
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 */


#ifndef CHARACTERISTICS_H
#define CHARACTERISTICS_H

#include "SubbandBits.h"


// r == row, c == col, s== subband.
int is_on_border(const SubbandBits *sb, int r, int c);
int subband_orientation(int s);

// bp == bitplane; use bp== -1 for sign bit. 
int bitplane_num(const SubbandBits *sb, int r, int c, int bp); // == bp except when bp==-1, use sig_level.
int is_sign(const SubbandBits *sb, int r, int c, int bp); // sign bit
int is_sig(const SubbandBits *sb, int r, int c, int bp); // significance pass bit
int refine_level(const SubbandBits *sb, int r, int c, int bp); // == refinement bit #
int is_refine(const SubbandBits *sb, int r, int c, int bp); // refinement pass bit


// values possible for neighborSignificance values:
// -1 for insignificant (for groups, if there is at least one item in group and all are insig)
//  0 for does not exist (for groups, if all do not exist)
//  1 for precedes me in standard bit-ordering and significant at current bit-plane
//                   
//  2 for significant at previous bit-plane (for groups, if there is at least one sig in group)
typedef struct {
  int nw, n, ne, w, e, sw, s, se;
  int children;
  int descendants;
  int parent;
  int sl1, sl2; // spatially collocated in subband at same subband level. 
  int so; // subband orientation. 
} NeighborSignificance;


// bp == bitplane; use bp== -1 for sign bit. 
//  significance of signbits uses bp == (siglevel of coeff) 
void computeNeighborSignificance(const SubbandComponent *sc, int r, int c, int s, int bp, NeighborSignificance *ns);

// values possible for neighborSigns:
// -1 for negative
// 0 for still insignificant or doesn't exist.
// 1 for positive. 
typedef struct {
  int n, w, e, s;
  int so; // subband orientation
} NeighborSigns;
void computeNeighborSigns(const SubbandComponent *sc, int r, int c, int s, int bp, NeighborSigns *ns);

// ebcot-like characteristics. 
int sig_h(const NeighborSignificance *ns);
int sig_v(const NeighborSignificance *ns);
int sig_d(const NeighborSignificance *ns);
int sig_label(const NeighborSignificance *ns);
int sign_hs(const NeighborSigns *ns);
int sign_vs(const NeighborSigns *ns);
int sign_label(const NeighborSigns *ns);
int refine_label(const NeighborSignificance *ns, const SubbandBits *sb, int r, int c,  int bp);

// gtw-like characteristics. 
int sig_count(const NeighborSignificance *ns);

int sig_count_8Neighb(const SubbandComponent *sc, int r, int c, int s, int bp);


typedef struct {
  char *name;
  char *description;
  char *ccdline;
  int (*f)(const SubbandComponent *, int, const NeighborSignificance *, 
	const NeighborSigns *, int, int, int, int);
  // add second function pointer here for color images.

  int numvalues; // number of different "buckets"
  int valuestart; // min value of a bucket
    // note: each bucket must either be a single value, or one of the end ranges
    //  (like (-3)-   or 5+. No buckets can have multiple values unless
    // they are an end range. 
} Characteristic;

extern Characteristic AllC[128];
void InitAllC(int numSubbands, int numbitplanes); // use -1 for bitplanes when unknown. 
// numSubbands must be filled in. 

// list all characteristics here, these are indexes into AllC array. 
#define IS_ON_BORDER 0
#define SUBBAND_ORIENTATION 1
#define IS_SIGN 2
#define IS_SIG 3
#define BITPLANE_NUM 4
#define REFINE_LEVEL 5
#define IS_REFINE 6
#define NSIG_NW 7
#define NSIG_N 8
#define NSIG_NE 9
#define NSIG_W 10
#define NSIG_E 11
#define NSIG_SW 12
#define NSIG_S 13
#define NSIG_SE 14
#define NSIG_CHILDREN 15
#define NSIG_DESCENDANTS 16
#define NSIG_PARENT 17
#define NSIG_SL1 18
#define NSIG_SL2 19
#define NSIGN_N 20
#define NSIGN_S 21
#define NSIGN_E 22
#define NSIGN_W 23
#define SUBBAND_NUM 24
#define NSIG_NW_01 25
#define NSIG_N_01 26
#define NSIG_NE_01 27
#define NSIG_W_01 28
#define NSIG_E_01 29
#define NSIG_SW_01 30
#define NSIG_S_01 31
#define NSIG_SE_01 32
#define SIG_H 33
#define SIG_V 34
#define SIG_D 35
#define SIG_LABEL 36
#define SIGN_HS 37
#define SIGN_VS 38
#define SIGN_LABEL 39
#define REFINE_LABEL 40
#define SIG_COUNT 41
#define SIG_COUNT_GTW 42
#define REVERSE_SUBBAND_LEVEL 43
// color subband characteristics
#define COMPONENT_NUM 44
#define NSIG_COMP0 45
#define NSIG_COMP1 46
#define NSIG_COMP2 47
#define NBITVAL_COMP0 48
#define NBITVAL_COMP1 49
#define NBITVAL_COMP2 50

//debugging charac.
#define SUBBAND_ROW 51
#define SUBBAND_COL 52

#define TOTAL_NUM_CHARACTERISTICS 53


// outputflags should be size 2 sequence of longs. 
// return is error flag
int getCharacteristicSet(int CharacteristicType, unsigned long long *outputflags) ;

// adds color characteristics to exisiting set of outputflags. 
int addColorCharacteristicSet(int ColorCharacteristicType, unsigned long long *outputflags) ;
// (colorCharacteristic types are different than CharacteristicTypes). 

// returns 1 if flag at position x is set. 
int checkflag(int x, const unsigned long long *flags);

void addflag(int x, unsigned long long *flags);
void removeflag(int x, unsigned long long *flags);


#endif /* CHARACTERISTICS_H */
